package com.qc.sys.utils;


import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.qc.common.utils.CacheUtils;
import com.qc.common.utils.SpringContextHolder;
import com.qc.common.utils.StringUtils;
import com.qc.sys.dao.MenuDao;
import com.qc.sys.dao.RoleDao;
import com.qc.sys.dao.UserDao;
import com.qc.sys.entity.Menu;
import com.qc.sys.entity.Role;
import com.qc.sys.entity.User;
import com.qc.sys.security.SystemAuthorizingRealm;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.UnavailableSecurityManagerException;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;

import java.util.List;
import java.util.Map;

/**
 * 用户工具类
 */
public class UserUtils {

	private static UserDao userDao = SpringContextHolder.getBean(UserDao.class);
	private static RoleDao roleDao = SpringContextHolder.getBean(RoleDao.class);
	private static MenuDao menuDao = SpringContextHolder.getBean(MenuDao.class);

	public static final String USER_CACHE = "userCache";
	public static final String USER_CACHE_ID_ = "id_";
	public static final String USER_CACHE_LOGIN_NAME_ = "ln";

	public static final String CACHE_AUTH_INFO = "authInfo";
	public static final String CACHE_ROLE_LIST = "roleList";
	public static final String CACHE_MENU_LIST = "menuList";

	/**
	 * 根据ID获取用户
	 * @param id
	 * @return 取不到返回null
	 */
	public static User getUser(String id){
		User user = (User) CacheUtils.get(USER_CACHE, USER_CACHE_ID_ + id);
		if (user ==  null){
			user = userDao.get(id);
			if (user == null){
				return null;
			}
			user.setRoleList(roleDao.findList(new Role(id,"")));
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getName(), user);
		}
		return user;
	}

	/**
	 * 根据登录名获取用户
	 * @param loginName
	 * @return 取不到返回null
	 */
	public static User getByLoginName(String loginName){
		User user = (User)CacheUtils.get(USER_CACHE, USER_CACHE_LOGIN_NAME_ + loginName);
		if (user == null){
			user = userDao.getByLoginName(new User(null,loginName));
			if (user == null){
				return null;
			}
			user.setRoleList(roleDao.findList(new Role(loginName)));
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + loginName, user);
		}
		return user;
	}

	public static void updateCurrentUser(User user) {
		Subject subject = SecurityUtils.getSubject();
		if(subject.getPrincipal() instanceof User) {
			User oldUser = (User) subject.getPrincipal();
			CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + oldUser.getName());
			oldUser = user;
			CacheUtils.put(USER_CACHE, USER_CACHE_ID_ + user.getId(), user);
			CacheUtils.put(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getName(), user);
		}
	}
	/**
	 * 清除当前用户缓存
	 */
	public static void clearCache(){
		removeCache(CACHE_AUTH_INFO);
		removeCache(CACHE_ROLE_LIST);
		removeCache(CACHE_MENU_LIST);
		UserUtils.clearCache(getCurrentUser());
	}

	/**
	 * 清除指定用户缓存
	 * @param user
	 */
	public static void clearCache(User user){
		CacheUtils.remove(USER_CACHE, USER_CACHE_ID_ + user.getId());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getName());
		CacheUtils.remove(USER_CACHE, USER_CACHE_LOGIN_NAME_ + user.getOldLoginName());
	}

	/**
	 * 获取当前用户
	 * @return 取不到返回 new User()
	 */
	public static User getCurrentUser(){
		Subject subject = SecurityUtils.getSubject();
		if(subject.getPrincipal() instanceof User) {
			return (User) subject.getPrincipal();
		}else {
			return null;
		}
	}

	/**
	 * 获取当前用户角色列表
	 * @return
	 */
	public static List<Role> getRoleList(){
		@SuppressWarnings("unchecked")
		List<Role> roleList = (List<Role>)getCache(CACHE_ROLE_LIST);
		if (roleList == null){
			User user = getCurrentUser();
			if (user.isAdmin()){
				roleList = roleDao.findList(new Role());
			}else{
				Role role = new Role();
				roleList = roleDao.findList(role);
			}
			putCache(CACHE_ROLE_LIST, roleList);
		}
		return roleList;
	}

	/**
	 * 获取当前用户授权菜单
	 * @return
	 */
	public static List<Menu> getSlideMenuList(){
		List<Menu> menuList =null;
		User user = getCurrentUser();
		if (user.isAdmin()){
			menuList = menuDao.findList(new Menu());
		}else{
			menuList = menuDao.findByUserId(user.getId());
		}
		List<Menu> newMenuList = Lists.newArrayList();
		int level1=0,level2=0,level3=0;
		for(Menu menu:menuList){
			String nodeID = menu.getNodeId();
			switch (nodeID.length()/Menu.nodeLength){
				case 1:
					level1++;
					if(level2>0){
						level2=0;
						level3=0;
					}
					newMenuList.add(menu);
					break;
				case 2:
					level2++;
					if(level3>0) {
						level3 = 0;
					}
					newMenuList.get(level1-1).getSubMenuList().add(menu);
					break;
				case 3:
					level3++;
					newMenuList.get(level1-1).getSubMenuList().get(level2-1).getSubMenuList().add(menu);
					break;
			}
		}
		return newMenuList;
	}

	/**
	 * 获取当前用户授权菜单
	 * @return
	 */
	public static List<Map<String,Object>> getMenuTreeList(String defaultSelectedId, String defaultCheckedIds){
		List<Menu> menuList = (List<Menu>)getCache(CACHE_MENU_LIST);
		if (menuList ==null||menuList.size()==0){
			menuList = Lists.newArrayList();
			User user = getCurrentUser();
			if (user.isAdmin()){
				menuList = menuDao.findList(new Menu());
			}
			putCache(CACHE_MENU_LIST, menuList);
		}
		List<Map<String,Object>> newMenuList = Lists.newArrayList();
		int level1=0,level2=0,level3=0;
		for(Menu menu:menuList){
			Map<String, Object> result = Maps.newHashMap();
			result.put("id", menu.getId());
			result.put("pid", menu.getNodeId());
			result.put("parentId", menu.getParentId());
			result.put("text", menu.getName());
			result.put("isShow", menu.getIsShow());

			if (StringUtils.isNotBlank(defaultSelectedId) && StringUtils.inString(menu.getNodeId(), defaultSelectedId.split(","))) {
				Map<String, Object> tmp = (Map<String, Object>) result.get("state");
				if (tmp == null) tmp = Maps.newHashMap();
				tmp.put("selected", true);
				result.put("state", tmp);
			}
			if (StringUtils.isNotBlank(defaultCheckedIds) && StringUtils.inString(menu.getId(), defaultCheckedIds.split(","))) {
				Map<String, Object> tmp = (Map<String, Object>) result.get("state");
				if (tmp == null) tmp = Maps.newHashMap();
				tmp.put("checked", true);
				result.put("state", tmp);
			}
			String nodeID = menu.getNodeId();
			switch (nodeID.length()/Menu.nodeLength){
				case 1:
					level1++;
					if(level2>0){
						level2=0;
						level3=0;
					}
					newMenuList.add(result);
					break;
				case 2:
					level2++;
					if(level3>0) {
						level3 = 0;
					}
					Map<String, Object> resultLevel2 =newMenuList.get(level1-1);
					List<Map<String,Object>> menuListLevel2 = (List<Map<String,Object>>)resultLevel2.get("nodes");
					if(menuListLevel2==null) {
						menuListLevel2 = Lists.newArrayList();
						resultLevel2.put("nodes", menuListLevel2);
					}
					menuListLevel2.add(result);
					break;
				case 3:
					level3++;
					Map<String, Object> resultLevel3 =newMenuList.get(level1-1);
					List<Map<String,Object>> menuListLevel3 = (List<Map<String,Object>>)resultLevel3.get("nodes");
					Map<String, Object> resultLevel4 =menuListLevel3.get(level2-1);
					List<Map<String,Object>> menuListLevel4 = (List<Map<String,Object>>)resultLevel4.get("nodes");
					if(menuListLevel4==null) {
						menuListLevel4 = Lists.newArrayList();
						resultLevel4.put("nodes", menuListLevel4);
					}
					menuListLevel4.add(result);
					break;
			}
		}
		return newMenuList;
	}
	/**
	 * 获取授权主要对象
	 */
	public static Subject getSubject(){
		return SecurityUtils.getSubject();
	}


	public static Session getSession(){
		try{
			Subject subject = SecurityUtils.getSubject();
			Session session = subject.getSession(false);
			if (session == null){
				session = subject.getSession();
			}
			if (session != null){
				return session;
			}
//			subject.logout();
		}catch (InvalidSessionException e){

		}
		return null;
	}

	// ============== User Cache ==============

	public static Object getCache(String key) {
		return getCache(key, null);
	}

	public static Object getCache(String key, Object defaultValue) {
//		Object obj = getCacheMap().get(key);
		Object obj = getSession().getAttribute(key);
		return obj==null?defaultValue:obj;
	}

	public static void putCache(String key, Object value) {
//		getCacheMap().put(key, value);
		getSession().setAttribute(key, value);
	}

	public static void removeCache(String key) {
//		getCacheMap().remove(key);
		getSession().removeAttribute(key);
	}

	/**
	 * 登录错误次数判断  错误五次禁止提交
	 * @param useruame 用户名
	 * @param isFail 计数加1
	 * @param clean 计数清零
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static boolean isValidateCodeLogin(String useruame, boolean isFail, boolean clean){
		Map<String, Integer> loginFailMap = (Map<String, Integer>) CacheUtils.get("loginFailMap");
		if (loginFailMap==null){
			loginFailMap = Maps.newHashMap();
			CacheUtils.put("loginFailMap", loginFailMap);
		}
		Integer loginFailNum = loginFailMap.get(useruame);
		if (loginFailNum==null){
			loginFailNum = 0;
		}
		if (isFail){
			loginFailNum++;
			loginFailMap.put(useruame, loginFailNum);
		}
		if (clean){
			loginFailMap.remove(useruame);
		}
//		return loginFailNum >= 5;
		return false;
	}
}
